<template>
  <div class="ai-chat-container">
    <div class="chat-messages" ref="chatContainer">
      <div
        v-for="(message, index) in messages"
        :key="index"
        :class="['message', message.type]"
      >
        <div>
          <AIText :rawContent="message.content"></AIText>
        </div>
      </div>
      <div class="think-message" v-show="thinking">正在思考中...</div>
    </div>
    <div class="input-area">
      <el-input
        v-model="input"
        placeholder="请输入消息"
        @keydown.enter.native="sendMessage"
      >
        <template #append>
          <el-button
            type="primary"
            @click="sendMessage"
            :disabled="isButtonDisabled"
            >发送</el-button
          >
        </template>
      </el-input>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { SSE } from "sse.js";
import {
  ref,
  onMounted,
  watch,
  nextTick,
  watchEffect,
  onBeforeUnmount,
} from "vue";
import AIText from "./AIText.vue";
import { useAuthStore } from "@/stores/auth";
import { ChatResponse } from "@/tsChatResponse";
import { MessageType } from "@/ts/MessageType";
import { httpClient } from "@/libs/http-client";
import { ElMessage } from "element-plus";
import { send } from "vite";

// token
const authStore = useAuthStore();

// 输入框
const input = ref("");
const chatString = ref("");
const messages = ref<Array<MessageType>>([]);
const chatContainer = ref<HTMLElement | null>(null);
// 发送按钮的可用性
const isButtonDisabled = ref(false);
// props
const props = defineProps(["sessionId"]);
// 当前界面的sessionId
const currentSessionId = ref(0);
// 发送锁,同时是sessionId的锁
let sending = false;
// 锁定sessionId
let lockSessionId = ref(0);
// thinking
const thinking = ref(false);

// watch sessionId的变化，如果变化了，重新初始化聊天
watch(
  () => props.sessionId,
  (newSessionId) => {
    console.log("Active session changed:", newSessionId);
    currentSessionId.value = newSessionId;
    initializeChat(); // 重新初始化聊天
  }
);

const evtSource = new SSE("http://localhost:9090/ai/PostSSEStream", {
  withCredentials: true,
  // 禁用自动启动，需要调用stream()方法才能发起请求
  start: false,
  // 携带token
  headers: {
    "Content-Type": "application/json",
    Authorization: authStore.token,
  },
  method: "POST",
});

evtSource.addEventListener("message", async (event: any) => {
  const response = JSON.parse(event.data) as ChatResponse;
  if (response.result.output.text) {
    chatString.value += response.result.output.text;

    if (messages.value.length === 0) {
      messages.value.push({ type: "ai", content: "" });
    }

    // //替换messages中最后一个消息的content
    messages.value[messages.value.length - 1].content = chatString.value;
  }
  //判断是否完成
  if (response.result.metadata.finishReason === "STOP") {
    // 退出思考状态
    thinking.value = false;
    // 处理完成的消息
    console.log("处理完成的消息:", chatString.value);
    // 保存消息
    await savaLatestTwoMessage();

    // 置空chatString
    chatString.value = "";
    // 解锁
    unlockSession();
  }
});
evtSource.addEventListener("error", async (event: any) => {
  ElMessage.error("对话太频繁啦！请休息一下吧！");
});

const sendMessage = async () => {
  // 检查当前是否有未完成的消息
  if (sending) {
    ElMessage.warning("当前有未完成的消息，无法发送新的消息");
    return;
  }
  // 锁定
  lockSession();

  if (input.value.trim() === "") {
    ElMessage.warning("消息不能为空");
    // 解锁
    unlockSession();
    return;
  }
  messages.value.push({ type: "user", content: input.value });
  // 滚动到底部
  scrollToBottom();
  // 进入思考中
  thinking.value = true;
  const userMessage = input.value;
  input.value = "";

  chatString.value = "";
  evtSource.payload = JSON.stringify({
    message: userMessage,
    sessionId: currentSessionId.value,
  });
  //给messages添加新的消息
  messages.value.push({ type: "assistant", content: "" });
  evtSource.stream();
};

const initializeChat = async () => {
  // 检查当前sending是否为true
  if (sending) {
    ElMessage.warning("当前有未完成的消息，无法切换页面");
    return;
  }
  // 获取当前的sessionId的聊天记录
  messages.value = [];
  const initSessionId = currentSessionId.value;
  if (!initSessionId) return;
  await httpClient
    .get<MessageType[]>(`/message/getAll/${initSessionId}`)
    .then((data) => {
      messages.value = data;
    });
};

const lockSession = () => {
  sending = true;
  lockSessionId.value = currentSessionId.value;
  isButtonDisabled.value = true;
};
const unlockSession = () => {
  sending = false;
  lockSessionId.value = 0;
  isButtonDisabled.value = false;
};

const saveMessage = async (message: MessageType) => {
  // 保存聊天记录
  const SaveSessionId = currentSessionId.value;
  if (!SaveSessionId) return;
  await httpClient
    .post(`/message/save`, {
      sessionId: SaveSessionId,
      type: message.type,
      content: message.content,
    })
    .then((data) => {});
};
// 保存用户的消息
const saveUserMessage = async (content: string) => {
  const data = {
    type: "user",
    content: content,
    sessionId: lockSessionId.value,
  };
  await saveMessage(data);
};
// 保存assistant的消息
const saveAssistantMessage = async (content: string) => {
  const data = {
    type: "assistant",
    content: content,
    sessionId: lockSessionId.value,
  };
  await saveMessage(data);
};
const savaLatestTwoMessage = async () => {
  // 保存聊天记录
  await saveUserMessage(messages.value[messages.value.length - 2].content);
  await saveAssistantMessage(messages.value[messages.value.length - 1].content);
};
// 初始化聊天,并滚动到底部
onMounted(async () => {
  await initializeChat();
  scrollToBottom();
});

// 离开界面时,尝试关闭SSE流，如果失败则表示流没有开启，如果成功则表示流已经开启,则保存消息
onBeforeUnmount(() => {
  // 保存AI的消息
  try {
    evtSource.close();
    // 检查思考的状态,如果还是锁定的,则保存消息
    if (thinking.value) savaLatestTwoMessage();
  } catch (error) {
    console.log("error:", error);
  }
});
// watch messages的变化,如果变化了,则滚动到底部
watch(messages, () => {
  nextTick(() => {
    if (chatContainer.value) {
      chatContainer.value.scrollTop = chatContainer.value.scrollHeight;
    }
  });
});

const isAtBottom = ref(true);
// 检查是否在底部
const checkIfAtBottom = () => {
  if (!chatContainer.value) return;

  const { scrollTop, scrollHeight, clientHeight } = chatContainer.value;
  isAtBottom.value = scrollTop + clientHeight >= scrollHeight - 100; // 允许 10px 的误差
};

// 滚动到底部
const scrollToBottom = () => {
  if (!chatContainer.value) return;

  chatContainer.value.scrollTop = chatContainer.value.scrollHeight;
};
// 监听消息变化
watch(
  () => messages.value,
  () => {
    nextTick(() => {
      checkIfAtBottom();
      if (isAtBottom.value) {
        scrollToBottom();
      }
    });
  },
  { deep: true }
);
</script>

<style scoped>
.ai-chat-container {
  display: flex;
  flex-direction: column;
  height: 90vh;
  width: 100%;
  margin: 0 auto;
}

.chat-messages {
  flex-grow: 1;
  overflow-y: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  max-height: calc(100% - 80px);
  width: 100%;
}

.message {
  max-width: 70%;
  margin-bottom: 10px;
  padding: 0px 16px;
  border-radius: 10px;
}

.think-message {
  align-self: flex-start;
  margin-left: 20px;
}
.ai {
  align-self: flex-start;
  background-color: #f0f0f0;
}

.user {
  align-self: flex-end;
  background-color: #007bff;
  color: white;
}

.input-area {
  padding: 20px;
}
</style>
